package com.eduagent.xwqeduagent.api.DocumentTranslation.api;

import com.eduagent.xwqeduagent.api.DocumentTranslation.constant.DocumentTranslationConstant;
import com.eduagent.xwqeduagent.api.DocumentTranslation.model.DocumentInfo;
import com.eduagent.xwqeduagent.api.DocumentTranslation.model.DocumentTranslationResponse;
import com.eduagent.xwqeduagent.api.DocumentTranslation.util.AuthUtils;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.TreeMap;

/**
 * Implementation of document translation API
 */
@Slf4j
public class DocumentTranslationApiImpl implements DocumentTranslationApi {

    private final String apiKey;
    private final String appId;
    private final RestTemplate restTemplate;
    private final ObjectMapper objectMapper;

    /**
     * Constructor
     *
     * @param apiKey API key
     * @param appId Application ID
     */
    public DocumentTranslationApiImpl(String apiKey, String appId) {
        this.apiKey = apiKey;
        this.appId = appId;
        this.restTemplate = new RestTemplate();
        this.objectMapper = new ObjectMapper();
        // Configure ObjectMapper to ignore unknown properties
        this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    @Override
    public DocumentTranslationResponse uploadAndTranslate(String from, String to, File file, Integer realmCode,
                                                         String termId, String memoryId, Integer processingMode) {
        try {
            // Create parameters map
            TreeMap<String, Object> params = new TreeMap<>();
            params.put("from", from);
            params.put("to", to);
            
            // Add optional parameters if provided
            if (realmCode != null) {
                params.put("realmCode", realmCode);
            }
            if (termId != null && !termId.isEmpty()) {
                params.put("termId", termId);
            }
            if (memoryId != null && !memoryId.isEmpty()) {
                params.put("memoryId", memoryId);
            }
            if (processingMode != null) {
                params.put("processingMode", processingMode);
            }
            
            // Generate auth parameters
            params = AuthUtils.generateAuthParams(params, apiKey, appId);
            
            // Create multipart request
            MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
            for (String key : params.keySet()) {
                body.add(key, params.get(key));
            }
            body.add("file", new FileSystemResource(file));
            
            // Set headers
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.MULTIPART_FORM_DATA);
            
            // Create request entity
            HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
            
            // Make API call
            ResponseEntity<String> response = restTemplate.exchange(
                    DocumentTranslationConstant.UPLOAD_TRANSLATE_URL,
                    HttpMethod.POST,
                    requestEntity,
                    String.class
            );
            
            // Parse response
            DocumentTranslationResponse translationResponse = objectMapper.readValue(
                    response.getBody(),
                    DocumentTranslationResponse.class
            );
            
            return translationResponse;
        } catch (Exception e) {
            log.error("Error uploading and translating file: {}", e.getMessage(), e);
            DocumentTranslationResponse errorResponse = new DocumentTranslationResponse();
            errorResponse.setCode(500);
            errorResponse.setMsg("Error: " + e.getMessage());
            return errorResponse;
        }
    }

    @Override
    public DocumentInfo getDocumentInfo(String fileNo) {
        try {
            // Create parameters map
            TreeMap<String, Object> params = new TreeMap<>();
            
            // Generate auth parameters
            params = AuthUtils.generateAuthParams(params, apiKey, appId);
            
            // Build URL with parameters
            String url = String.format(DocumentTranslationConstant.STATUS_URL, fileNo);
            UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url);
            
            // Add parameters to URL
            for (String key : params.keySet()) {
                builder.queryParam(key, params.get(key));
            }
            
            // Make API call
            ResponseEntity<String> response = restTemplate.exchange(
                    builder.toUriString(),
                    HttpMethod.GET,
                    null,
                    String.class
            );
            
            // Parse response
            DocumentTranslationResponse translationResponse = objectMapper.readValue(
                    response.getBody(),
                    DocumentTranslationResponse.class
            );
            
            // Convert data to DocumentInfo
            if (translationResponse.getCode() == 200 && translationResponse.getData() != null) {
                return objectMapper.convertValue(translationResponse.getData(), DocumentInfo.class);
            } else {
                log.error("Error getting document info: {}", translationResponse.getMsg());
                return null;
            }
        } catch (Exception e) {
            log.error("Error getting document info: {}", e.getMessage(), e);
            return null;
        }
    }

    @Override
    public boolean interruptTranslation(String fileNo) {
        try {
            // Create parameters map
            TreeMap<String, Object> params = new TreeMap<>();
            
            // Generate auth parameters
            params = AuthUtils.generateAuthParams(params, apiKey, appId);
            
            // Build URL with parameters
            String url = String.format(DocumentTranslationConstant.INTERRUPT_URL, fileNo);
            UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url);
            
            // Add parameters to URL
            for (String key : params.keySet()) {
                builder.queryParam(key, params.get(key));
            }
            
            // Make API call
            ResponseEntity<String> response = restTemplate.exchange(
                    builder.toUriString(),
                    HttpMethod.PUT,
                    null,
                    String.class
            );
            
            // Parse response
            DocumentTranslationResponse translationResponse = objectMapper.readValue(
                    response.getBody(),
                    DocumentTranslationResponse.class
            );
            
            // Check if operation was successful
            if (translationResponse.getCode() == 200 && translationResponse.getData() != null) {
                return Boolean.TRUE.equals(translationResponse.getData());
            } else {
                log.error("Error interrupting translation: {}", translationResponse.getMsg());
                return false;
            }
        } catch (Exception e) {
            log.error("Error interrupting translation: {}", e.getMessage(), e);
            return false;
        }
    }

    @Override
    public boolean downloadFile(String fileNo, Integer type, String savePath) {
        try {
            // Create parameters map
            TreeMap<String, Object> params = new TreeMap<>();
            params.put("type", type);
            
            // Generate auth parameters
            params = AuthUtils.generateAuthParams(params, apiKey, appId);
            
            // Build URL with parameters
            String url = String.format(DocumentTranslationConstant.DOWNLOAD_URL, fileNo);
            UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url);
            
            // Add parameters to URL
            for (String key : params.keySet()) {
                builder.queryParam(key, params.get(key));
            }
            
            // Make API call to get file data
            ResponseEntity<byte[]> response = restTemplate.exchange(
                    builder.toUriString(),
                    HttpMethod.GET,
                    null,
                    byte[].class
            );
            
            // Create directory if it doesn't exist
            Path directory = Paths.get(savePath).getParent();
            if (directory != null && !Files.exists(directory)) {
                Files.createDirectories(directory);
            }
            
            // Save file
            try (FileOutputStream outputStream = new FileOutputStream(savePath)) {
                outputStream.write(response.getBody());
            }
            
            return true;
        } catch (Exception e) {
            log.error("Error downloading file: {}", e.getMessage(), e);
            return false;
        }
    }

    @Override
    public String getDownloadUrl(String fileNo, Integer type) {
        try {
            // Create parameters map
            TreeMap<String, Object> params = new TreeMap<>();
            params.put("type", type);
            
            // Generate auth parameters
            params = AuthUtils.generateAuthParams(params, apiKey, appId);
            
            // Build URL with parameters
            String url = String.format(DocumentTranslationConstant.DOWNLOAD_URL_ENDPOINT, fileNo);
            UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url);
            
            // Add parameters to URL
            for (String key : params.keySet()) {
                builder.queryParam(key, params.get(key));
            }
            
            // Make API call
            ResponseEntity<String> response = restTemplate.exchange(
                    builder.toUriString(),
                    HttpMethod.GET,
                    null,
                    String.class
            );
            
            // Parse response
            DocumentTranslationResponse translationResponse = objectMapper.readValue(
                    response.getBody(),
                    DocumentTranslationResponse.class
            );
            
            // Return download URL
            if (translationResponse.getCode() == 200 && translationResponse.getData() != null) {
                return translationResponse.getData().toString();
            } else {
                log.error("Error getting download URL: {}", translationResponse.getMsg());
                return null;
            }
        } catch (Exception e) {
            log.error("Error getting download URL: {}", e.getMessage(), e);
            return null;
        }
    }

    @Override
    public boolean deleteFile(String fileNo) {
        try {
            // Create parameters map
            TreeMap<String, Object> params = new TreeMap<>();
            
            // Generate auth parameters
            params = AuthUtils.generateAuthParams(params, apiKey, appId);
            
            // Build URL with parameters
            String url = String.format(DocumentTranslationConstant.DELETE_URL, fileNo);
            UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url);
            
            // Add parameters to URL
            for (String key : params.keySet()) {
                builder.queryParam(key, params.get(key));
            }
            
            // Make API call
            ResponseEntity<String> response = restTemplate.exchange(
                    builder.toUriString(),
                    HttpMethod.DELETE,
                    null,
                    String.class
            );
            
            // Parse response
            DocumentTranslationResponse translationResponse = objectMapper.readValue(
                    response.getBody(),
                    DocumentTranslationResponse.class
            );
            
            // Check if operation was successful
            if (translationResponse.getCode() == 200 && translationResponse.getData() != null) {
                return Boolean.TRUE.equals(translationResponse.getData());
            } else {
                log.error("Error deleting file: {}", translationResponse.getMsg());
                return false;
            }
        } catch (Exception e) {
            log.error("Error deleting file: {}", e.getMessage(), e);
            return false;
        }
    }
} 